// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: Apache-2.0

package user_dao

import (
	"context"

	"gitcode.com/lvupclub/lvup-api/dao/common"
	"gitcode.com/lvupclub/proto-gen-go.git/src/user_api"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

type BasicUserInfoDbItem struct {
	DisplayName  string             `bson:"displayName"`
	LogoUri      string             `bson:"logoUri"`
	UserRole     user_api.USER_ROLE `bson:"userRole"`
	PublicAccess bool               `bson:"publicAccess"`
	UserIntro    string             `bson:"userIntro"`
}

type UserInfoDbItem struct {
	UserId     string              `bson:"_id"`
	UserType   user_api.USER_TYPE  `bson:"userType"`
	UserName   string              `bson:"userName"`
	BasicInfo  BasicUserInfoDbItem `bson:"basicInfo"`
	CreateTime int64               `bson:"createTime"`
	UpdateTime int64               `bson:"updateTime"`
}

func (item *UserInfoDbItem) ToUserInfo() *user_api.UserInfo {
	return &user_api.UserInfo{
		UserId:   item.UserId,
		UserType: item.UserType,
		UserName: item.UserName,
		BasicInfo: &user_api.BasicUserInfo{
			DisplayName:  item.BasicInfo.DisplayName,
			LogoUri:      item.BasicInfo.LogoUri,
			UserRole:     item.BasicInfo.UserRole,
			PublicAccess: item.BasicInfo.PublicAccess,
			UserIntro:    item.BasicInfo.UserIntro,
		},
		CreateTime: item.CreateTime,
		UpdateTime: item.UpdateTime,
	}
}

type _UserInfoDao struct {
	mc *mongo.Collection
}

func newUserInfoDao(db *mongo.Database) (*_UserInfoDao, error) {
	mc := db.Collection(common.DB_NS_USER + "info")
	_, err := mc.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
		{
			Keys:    bson.D{{"userName", 1}, {"userType", 1}},
			Options: options.Index().SetUnique(true),
		},
		{
			Keys: bson.M{"createTime": 1},
		},
	})
	if err != nil {
		return nil, err
	}
	return &_UserInfoDao{mc: mc}, nil
}

func (db *_UserInfoDao) Insert(ctx context.Context, dbItem *UserInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_UserInfoDao) ExistByName(ctx context.Context, userType user_api.USER_TYPE, userName string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"userType": userType, "userName": userName})
	return count > 0, err
}

func (db *_UserInfoDao) ExistById(ctx context.Context, userId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"_id": userId})
	return count > 0, err
}

func (db *_UserInfoDao) GetByName(ctx context.Context, userType user_api.USER_TYPE, userName string) (*UserInfoDbItem, error) {
	retItem := &UserInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"userType": userType, "userName": userName}).Decode(retItem)
	return retItem, err
}

func (db *_UserInfoDao) GetById(ctx context.Context, userId string) (*UserInfoDbItem, error) {
	retItem := &UserInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"_id": userId}).Decode(retItem)
	return retItem, err
}

func (db *_UserInfoDao) UpdateBasic(ctx context.Context, userId string, basicInfo *BasicUserInfoDbItem, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": userId},
		bson.M{"$set": bson.M{"basicInfo": basicInfo, "updateTime": updateTime}})
	return err
}

func (db *_UserInfoDao) ListById(ctx context.Context, userIdList []string) ([]*UserInfoDbItem, error) {
	if len(userIdList) == 0 {
		return []*UserInfoDbItem{}, nil
	}
	cursor, err := db.mc.Find(ctx, bson.M{"_id": bson.M{"$in": userIdList}})
	if err != nil {
		return nil, err
	}
	retList := []*UserInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}
